/**
 * 根据 最长子节点 进行添加 数据
 * -
 * 实现 方式 是 在 每个 复制的最长子节点 前 进行 二分插入 中间的数据 一次循环 为一次扫描 并进行 扩充最长子节点
 * 直到扫描完毕 并检测 复制的最长子节点 数据 是否 与 原数据 完全相同 并进行 适当补充
 * 每次 运行 就实际添加 重新计算 目标应放置位置
 */

import {
  addCompsH,
  removeCompsH,
} from '../../../../../testComps/formTable/TaddNewComsFunc';
import { fromtoAnimaF } from '../../fromToAnimate/fromToAnimaFunc';
import {
  domTree,
  endsTimeAnimation,
  getNum,
  removeClass,
  settimeNth,
} from '../../global';

/**
 * 复制的元数据
 */
let SourceArr;

console.log(SourceArr);

/**
 * 目标实现 数组
 */
let TargetArr;

/**
 * 复制的最长子节点
 */
let CLongArr;

/**
 * 递归次数
 */
let recu = 0;

/**
 * 每次递归之间的延迟
 */
let delayTime = 200;

/**
 * 临时 记录组件
 */
let tempComp = { data: [] };

// let selectedComps = {
//   data: ['e9325', 'a367', 'vasl'],
//   e9325: { weight: 16 },
//   a367: { weight: 43 },
//   vasl: { weight: 958 },
// };

let selectedComps;
/**
 * 绑定数据 临时 ----！！！
 * @param {Object} a 绑定实时 selectedComps 获取 实时的 选中组件信息
 */
function TwoWayBind(a) {
  console.log(a);
  selectedComps = a;
}

// let activeCompFirstEl;

function ShortWay(sourceArr, targetArr, ChildArr) {
  console.log(sourceArr, targetArr, ChildArr);
  SourceArr = [...sourceArr];
  CLongArr = [...ChildArr];
  TargetArr = [...targetArr];

  indeedCLongComps();

  recuCLongArr();
}

/**
 * 递归 cLongArr 进行添加 每个项 的 与前面一个项 的 中间 目标取值
 *
 * 并渲染 数据到Dom
 */
function recuCLongArr() {
  /**
   * 当前递归 是否有(某一项)拥有前一个值
   */
  let hasFront = false;

  /**
   * 临时 CLongArr 复制 版本 确保 每次循环 的基数
   */
  let dynamicArr = [...CLongArr];

  //获取 标准顺序 的 前一个中间值 进行 渲染组件 并记录 hasFront 设置有前一个值
  for (let i = 0; i < CLongArr.length; i++) {
    let DeepI = getFrontMidIndex(i);
    if ([false].indexOf(DeepI) == -1) {
      hasFront += true;
      //   添加 当前组件 到 dynamicArr
      dynamicArr.splice(i++, 0, TargetArr[DeepI]);

      //   渲染组件
      reRenderSelectedComp(TargetArr[DeepI]);
    }
  }
  //   console.log(recu, CLongArr);

  /**
   * 在 当前循环数据完成后 及时更迭 CLongArr 确保信息匹配
   */
  CLongArr = dynamicArr;

  if (hasFront) {
    recu++;

    if (CLongArr.length * 2 > TargetArr.length) {
      console.log(
        'fillComp -- 按 targetArr 目标 填充剩余项',
        CLongArr.length,
        recu,
        CLongArr
      );
      settimeNth([delayTime], () => {
        fillLastComp();
      });
    } else {
      settimeNth([delayTime], () => {
        recuCLongArr();
      });
    }
  }
  if (!hasFront) {
    console.log(
      'fillComp -- 按 targetArr 目标 填充剩余项',
      CLongArr.length,
      recu,
      CLongArr
    );
    settimeNth([delayTime], () => {
      fillLastComp();
    });
  }
}

/**
 * 创建 最初 最长子序列节点
 */
function indeedCLongComps() {
  for (let i = 0; i < CLongArr.length; i++) {
    // reRenderSelectedComp(CLongArr[i]);
    if (tempComp['data'].indexOf(CLongArr[i]) == -1) {
      tempComp['data'].push(CLongArr[i]);

      //记录 组件 关键信息
      tempComp[CLongArr[i]] = {
        weight: selectedComps[CLongArr[i]]['weight'],
        element: selectedComps[CLongArr[i]]['element'],
      };
    }
  }
  //   console.log(JSON.stringify(tempComp));
  console.log(tempComp);
}

/**
 * 获取 cLongArr 当前 值 和 前一个值 的 目标数组的中间位置
 * 如果已存在 则返回下一个值
 * 如果 下一个值 是 当前值 返回 false
 * @param {Number} currentI cLongArr 的 某一个索引
 * @returns
 */
function getFrontMidIndex(currentI) {
  let Sind =
    TargetArr.indexOf(CLongArr[currentI - 1]) > -1
      ? TargetArr.indexOf(CLongArr[currentI - 1])
      : 0;
  let Cind =
    TargetArr.indexOf(CLongArr[currentI]) > -1
      ? TargetArr.indexOf(CLongArr[currentI])
      : 0;

  let midI = Math.floor((Sind + Cind) / 2);

  if (CLongArr.indexOf(TargetArr[midI]) > -1) {
    midI++;
    if (CLongArr.indexOf(TargetArr[midI]) > -1) {
      return false;
    }
  }

  return midI;
}

/**
 * 填充 剩余 comp 组件
 */
function fillLastComp() {
  for (let i = 0; i < TargetArr.length; i++) {
    if (CLongArr.indexOf(TargetArr[i]) == -1) {
      CLongArr.splice(i, 0, TargetArr[i]);
      reRenderSelectedComp(TargetArr[i]);
    }
  }
}

/**
 * ShortWay 自定义 渲染组件
 * --
 * -- resort by asc 特别版 x-y> y-x>
 * 装载 组件模板 --opcity: 0; 直到 maxHeight 0 - 正常  durationTime/2
 * @param {String} value  组件名
 */
function reRenderSelectedComp(value) {
  //   console.log(value);

  //目标 容器
  let activeCompEl = document.getElementById('active_comps');

  //   //绑定 最开始的 常规元素 确保 新排序元素占据 顶部 --insertbefore
  //   activeCompFirstEl != undefined
  //     ? undefined
  //     : (activeCompFirstEl = activeCompEl.firstChild);

  //新生成 目标元素 domtree 解构
  let selectedComp_DomData = AssembleDomTree(value, 'remove');

  //--移动动画 1.  添加 主 透明
  //   selectedComp_DomData['r_body']['classList'].push('opacity0');

  //   生成目标元素 并 记录在 tempComp 临时组件 中
  let domT = domTree(undefined, selectedComp_DomData);
  domT.classList.add('opacity0');
  //   console.log(domT);

  //记录 组件 关键信息
  tempComp['data'].push(value);
  tempComp[value] = { weight: selectedComps[value]['weight'], element: domT };

  //挂载元素 到指定元素前 || 放置到 元素 最开始位置
  let mountBeforeEl = getMountBeforeEl(value);

  //   activeCompEl.insertBefore(domT, mountBeforeEl || activeCompFirstEl);
  // 插到预定节点前面
  activeCompEl.insertBefore(domT, mountBeforeEl || null);

  //--移动动画 1.9.9 开启工厂
  // 设置 usedom 元素
  //   let animationF = fromtoAnimaF(tempComp[value]['element']);
  let animationF = fromtoAnimaF(selectedComps[value]['element']);

  animationF.addBeforeAnimaFuncS('opcity0UseDom', opcity0UseDom);

  //-- 移动动画 2.3 启用动画后 删除 useDom
  animationF.addAfterAnimaFuncS('removeUseDom', removeUseDom);

  /**
   * 临时 补充
   */
  //   selectedComps[value]['element'] = document.getElementById(
  //     'selected_' + value
  //   );
  //   console.log(value, selectedComps[value]['element']);
  //   console.log(domT.id, domT);

  //--移动动画 2.0 启用动画
  animationF.fromElto(selectedComps[value]['element'], domT);

  let disnoneDuraTime = disDuraTime(domT);

  //--移动动画 3.  移除 目标元素 透明
  endsTimeAnimation(domT, 'opacity0', 0, disnoneDuraTime);

  endsTimeAnimation(domT, 'rebackCompsAnimation');
}

function disDuraTime(el) {
  let compEl = window.getComputedStyle(el);
  return getNum(compEl['animation-duration']) * 1000;
}

/**
 * 组装 DomTree
 * @param {String} value 目标 唯一 ID
 * @param {String} AddorRemove "add" | "remove"
 * @returns
 */
function AssembleDomTree(value, AddorRemove) {
  let domTree;
  if (AddorRemove == 'add') {
    domTree = {
      queue: ['a_body'],
      a_body: {
        tag: 'div',
        props: ['classList', 'id'],
        attribute: ['value'],
        classList: ['uni_comp', 'bunt_getme'],
        id: `wait_${value}`,
        value: [value],

        queue: ['a_span', 'a_btn'],
        a_span: {
          tag: 'span',
          props: ['classList', 'id', 'innerHTML'],
          innerHTML: value,
          id: 'comp_text',
          classList: ['comp_text'],
        },
        a_btn: {
          tag: 'button',
          props: ['classList', 'id', 'innerHTML'],
          events: ['click'],
          innerHTML: '添加',
          id: 'add_btn',
          classList: ['comp_func_btn', 'func_add_btn', 'cursorPointer'],
          click: addCompsH,
        },
      },
    };
  }
  if (AddorRemove == 'remove') {
    domTree = {
      queue: ['r_body'],
      r_body: {
        tag: 'div',
        props: ['classList', 'id'],
        attribute: ['value'],
        classList: ['uni_comp', 'selected_comp', 'bunt_getme'],
        // classList: ['uni_comp', 'selected_comp', 'bunt_getme'],

        id: `selected_${value}`,

        value: [value],

        queue: ['r_span', 'r_btn'],
        r_span: {
          tag: 'span',
          props: ['classList', 'id', 'innerHTML'],
          innerHTML: value,
          id: 'comp_text',
          classList: ['comp_text'],
        },
        r_btn: {
          tag: 'button',
          props: ['classList', 'id', 'innerHTML'],
          events: ['click'],
          innerHTML: '移除',
          id: 'add_btn',
          classList: ['comp_func_btn', 'func_remove_btn', 'cursorPointer'],
          click: removeCompsH,
        },
      },
    };
  }
  return domTree;
}

function removeUseDom() {
  console.log('remove AnimaFunc class', this.currentDom.id, this.currentDom);

  removeClass(this.currentDom, 'default_FromToAnima_' + this.currentDom.id);

  this.currentDom.remove();
}

function opcity0UseDom() {
  // console.log();
}

/**
 * 获取 当前值 插入槽位
 * @param {String} value
 */
function getMountBeforeEl(value) {
  let index = CLongArr.indexOf(value);
  // 后面又 元素
  if (CLongArr[index + 1] != undefined) {
    return tempComp[CLongArr[index + 1]] != undefined
      ? tempComp[CLongArr[index + 1]]['element']
      : false;
  } else {
    return false;
  }
}

export { ShortWay, TwoWayBind };
